<?php

namespace addons\shopro\traits;

use addons\shopro\service\Wallet as WalletService;
use app\admin\model\shopro\commission\CommissionGoods;
use app\admin\model\shopro\commission\Log as LogModel;
use app\admin\model\shopro\commission\Reward;
use app\admin\model\shopro\commission\Reward as RewardModel;
use app\admin\model\shopro\commission\Reward1;
use app\admin\model\shopro\Config;
use app\admin\model\shopro\Config as ShoproConfig;
use app\admin\model\shopro\goods\Goods;
use app\admin\model\shopro\goods\SkuPrice;
use app\admin\model\shopro\app\ScoreSkuPrice;
use app\admin\model\shopro\activity\SkuPrice as ActivitySkuPriceModel;
use app\admin\model\shopro\order\OrderItem;
use addons\shopro\facade\ActivityRedis as ActivityRedisFacade;
use addons\shopro\facade\Redis;
use app\admin\model\shopro\user\WalletLog;
use app\common\model\User;
use think\Collection;
use think\Db;
use Yansongda\Pay\Logger;

/**
 * 库存销量
 */
trait StockSale
{
    use StockWarning;


    public function stockLock($buyInfo)
    {
        $goods = $buyInfo['goods'];

        // 普通商品还是积分商品
        $order_type = request()->param('order_type', '');
        $order_type = $order_type ?: 'goods';
        
        // 普通商品销量处理 (积分和普通商品的缓存 key 不相同)
        $keyGoodsLockedNum = $this->getLockedGoodsKey($buyInfo['goods_id'], $buyInfo['goods_sku_price_id'], $order_type);
        $locked_num = redis_cache($keyGoodsLockedNum);

        if ($order_type == 'score') {
            // 验证积分商品库存是否充足(mysql 悲观锁，此方法可靠，但如果大规模秒杀，容易mysql 死锁，请将商品添加为秒杀)
            $stock = ScoreSkuPrice::where('goods_id', $buyInfo['goods_id'])->where('goods_sku_price_id', $buyInfo['current_sku_price']->id)->lock(true)->value('stock');
            if (($stock - $locked_num) < $buyInfo['goods_num']) {
                error_stop('积分商品库存不足');
            }
        }

        // 验证商品库存是否充足(mysql 悲观锁，此方法可靠，但如果大规模秒杀，容易mysql 死锁，请将商品添加为秒杀)
        $stock = SkuPrice::where('id', $buyInfo['current_sku_price']->id)->lock(true)->value('stock');
        if (($stock - $locked_num) < $buyInfo['goods_num']) {
            error_stop('商品库存不足');
        }

        // 锁库存
        redis_cache()->INCRBY($keyGoodsLockedNum, $buyInfo['goods_num']);
    }


    public function stockUnLock($order)
    {
        $items = $order->items;

        foreach ($items as $key => $item) {
            $this->stockUnLockItem($item);
        }
    }

    public function stockUnLockItem($item)
    {
        $keyGoodsLockedNum = $this->getLockedGoodsKey($item['goods_id'], $item['goods_sku_price_id']);
        $locked_num = redis_cache()->DECRBY($keyGoodsLockedNum, $item->goods_num);

        if ($locked_num < 0) {
            $locked_num = redis_cache()->set($keyGoodsLockedNum, 0);
        }
    }



    // 真实正向 减库存加销量（支付成功扣库存，加销量）
    public function forwardStockSale($order) {
        $items = OrderItem::where('order_id', $order['id'])->select();

        foreach ($items as $key => $item) {
            // 增加商品销量
            Goods::where('id', $item->goods_id)->setInc('sales', $item->goods_num);

            $skuPrice = SkuPrice::where('id', $item->goods_sku_price_id)->find();
            if ($skuPrice) {
                SkuPrice::where('id', $item->goods_sku_price_id)->setDec('stock', $item->goods_num);         // 减少库存
                SkuPrice::where('id', $item->goods_sku_price_id)->setInc('sales', $item->goods_num);         // 增加销量
                // 库存预警检测
                $this->checkStockWarning($skuPrice);
            }

            if ($item->item_goods_sku_price_id) {
                if ($order['type'] == 'score') {
                    // 积分商城商品，扣除积分规格库存
                    ScoreSkuPrice::where('id', $item->item_goods_sku_price_id)->setDec('stock', $item->goods_num);     // 减少库存
                    ScoreSkuPrice::where('id', $item->item_goods_sku_price_id)->setInc('sales', $item->goods_num);
                } else {
                    // 扣除活动库存
                    ActivitySkuPriceModel::where('id', $item->item_goods_sku_price_id)->setDec('stock', $item->goods_num);     // 减少库存
                    ActivitySkuPriceModel::where('id', $item->item_goods_sku_price_id)->setInc('sales', $item->goods_num);
                }
            }

            // 真实库存已减，库存解锁(非活动)
            if (!$item['activity_id']) {
                $this->stockUnLockItem($item);
            }

            //查询是否是分销商品
            $shopGood = CommissionGoods::where('goods_id', $item->goods_id)->find();
            $sys_fund_give = ($shopGood['sys_fund_give'] ?? 0)*$item->goods_num;
            $sys_green_score_give = ($shopGood['sys_green_score_give'] ?? 0)*$item->goods_num;
            $green_scroe_give = ($shopGood['green_scroe_give'] ?? 0)*$item->goods_num;
            $level3_give = ($shopGood['level1_give'] ?? 0)*$item->goods_num;
            $level4_give = ($shopGood['level2_give'] ?? 0)*$item->goods_num;
            $level5_give = ($shopGood['level3_give'] ?? 0)*$item->goods_num;
            $level6_give = ($shopGood['level4_give'] ?? 0)*$item->goods_num;
            $level2_give = ($shopGood['level5_give'] ?? 0)*$item->goods_num;
            $level1_give = ($shopGood['level6_give'] ?? 0)*$item->goods_num;
            $level7_give = ($shopGood['level7_give'] ?? 0)*$item->goods_num;
            $userId = $item->user_id;
            \think\Log::info("订单{$order['id']}赠送系统资金{$sys_fund_give},系统积分{$sys_green_score_give},用户绿色积分{$green_scroe_give}");


            if($green_scroe_give > 0)
            {
                //赠送金
                WalletService::change($userId, WalletLog::GREEN_SCORE_GIFT_TYPE, $green_scroe_give, 'order_give', [
                    'order_id' => $order['id'],
                ]);
                $sys_fund = Config::getConfigs('shop.basic.sys_fund', false);;
                $sys_green_score = Config::getConfigs('shop.basic.sys_green_score', false);
                $perprice = $sys_fund/$sys_green_score;
                $perprice = sprintf("%.4f", $perprice);
                $give = sprintf("%.2f", $green_scroe_give/$perprice);
                //绿色积分
                \think\Log::info("单价{$perprice},绿色积分{$give}");
                WalletService::change($userId, WalletLog::GREEN_SCORE_TYPE, $give, 'order_give1', [
                    'order_id' => $order['id'],
                ], '', $perprice);
                Db::name('shopro_config')->query("update fa_shopro_config set value=value+{$give} where code ='shop.basic.sys_green_score'");
            }
            
            //系统资金增加
            if($sys_fund_give > 0)
            {
                $commissionRewardParams = [
                    'order_id' => $order['id'],
                    'order_item_id' => $item->id,
                    'buyer_id' => $userId,      // 购买人
                    'commission_order_id' => $order['id'],   // 分销订单ID
                    'agent_id' => $userId,           // 待分佣分销商ID
                    'type' => 'money',                               // 奖金类型
                    'commission' => $sys_fund_give,                     // 佣金
                    'status' => 1,                              // 佣金状态
                    'original_commission' => 0,            // 原始佣金
                    'commission_level' => 0,   // 分佣层级
                    'commission_rules' => '',   // 分佣层级
                    'agent_level' => 0,              // 分佣时分销商等级
                    'commission_time' => time()
                ];
                $commissionReward = Reward1::create($commissionRewardParams);
                //$configs = Db::name('shopro_config')->where(['code' =>'shop.basic.sys_fund'])->find();     //('shop.basic.sys_fund', false);
                //$value = $configs['value'] ?? 0;
                //$configs = Db::name('')['value' =>$value+$sys_fund_give])->where(['code' =>'shop.basic.sys_fund']);     //('shop.basic.sys_fund', false);
                Db::name('shopro_config')->query("update fa_shopro_config set value=value+{$sys_fund_give} where code ='shop.basic.sys_fund'");
                $sys_fund = Config::getConfigs('shop.basic.sys_fund', false);
                WalletService::change($userId, WalletLog::SYS_FUND_TYPE, $sys_fund_give, 'order_give2', [
                    'order_id' => $order['id'],
                ], '', $perprice, $sys_fund);
                //更新系统资金总数

                //LogModel::add($commissionReward['agent_id'], 'reward', [
                //    'type' => 'paid',
                //    'reward' => $commissionReward,
                //], $this->buyer->user);
            }
            //if($sys_green_score_give > 0)
            if(0)
            {
                $commissionRewardParams = [
                    'order_id' => $order['id'],
                    'order_item_id' => $item->id,
                    'buyer_id' => $userId,      // 购买人
                    'commission_order_id' => $order['id'],   // 分销订单ID
                    'agent_id' => $userId,           // 待分佣分销商ID
                    'type' => 'score',                               // 奖金类型
                    'commission' => $sys_green_score_give,                     // 佣金
                    'status' => 0,                              // 佣金状态
                    'original_commission' => 0,            // 原始佣金
                    'commission_level' => 0,   // 分佣层级
                    'commission_rules' => '',   // 分佣层级
                    'agent_level' => 0              // 分佣时分销商等级
                ];
                $commissionReward = Reward1::create($commissionRewardParams);
                //$configs = Config::get(['code' =>'shop.basic.sys_green_score'])->find();     //('shop.basic.sys_fund', false);
                //$value = $configs['value'] ?? 0;
                //$configs = Config::update(['value' =>$value+$sys_green_score_give])->where(['code' =>'shop.basic.sys_green_score']);
                Db::name('shopro_config')->query("update fa_shopro_config set value=value+{$sys_green_score_give} where code ='shop.basic.sys_green_score'");
                //LogModel::add($commissionReward['agent_id'], 'reward', [
                //    'type' => 'paid',
                //    'reward' => $commissionReward,
                //], $this->buyer->user);
            }
            //下单用户增加绿色积分赠送金
            //if($green_scroe_give > 0)
            if(0)
            {
                //赠送金
                WalletService::change($userId, WalletLog::GREEN_SCORE_GIFT_TYPE, $green_scroe_give, 'order_give', [
                    'order_id' => $order['id'],
                ]);
                $sys_fund = Config::getConfigs('shop.basic.sys_fund', false);;
                $sys_green_score = Config::getConfigs('shop.basic.sys_green_score', false);
                $perprice = $sys_fund/$sys_green_score;
                $perprice = sprintf("%.4f", $perprice);
                $give = sprintf("%.2f", $green_scroe_give/$perprice);
                //绿色积分
                \think\Log::info("单价{$perprice}");
                WalletService::change($userId, WalletLog::GREEN_SCORE_TYPE, $give, 'order_give1', [
                    'order_id' => $order['id'],
                ]);
                Db::name('shopro_config')->query("update fa_shopro_config set value=value+{$give} where code ='shop.basic.sys_green_score'");
            }

            \think\Log::info('开始找星星');
            //往上找第一个一星
            $level = 1;
            $tocommission = 0.8;
            $tomoney = 1 - $tocommission;
            $lastlevel=0;
            while($level <= 7)
            {
                \think\Log::info('星星'.$level);
                if($level > 7)
                {
                    break;
                }
                $agent = $this->getOneUpAgency($userId, $level);
                \think\Log::info('星星'.$level.'_res'.json_encode($agent));
                $levelTmp = "level{$level}_give";
                $levelTmp1num = $$levelTmp;
                $levelTmp1=$levelTmp1num-$lastlevel;
                $levelTmp1_2money = sprintf('%.5f', $levelTmp1*$tomoney);//20%去佣金
                $levelTmp1 = sprintf("%.5f", $levelTmp1*$tocommission);//佣金
                $level++;
                if($agent && $levelTmp1 > 0)
                {
                    $lastlevel=$levelTmp1num;
                    $level=$agent['level'];
                    \think\Log::info('找到'.$level);
                    $commissionRewardParams = [
                        'order_id' => $order['id'],
                        'order_item_id' => $item->id,
                        'buyer_id' => $agent['id'],      // 购买人
                        'commission_order_id' => $order['id'],   // 分销订单ID
                        'agent_id' => $agent['id'],           // 待分佣分销商ID
                        'type' => 'commission',                               // 奖金类型
                        'commission' => $levelTmp1,                     // 佣金
                        //'status' => 0,                              // 佣金状态
                        'status' => 1,                              // 佣金状态
                        'original_commission' => 0,            // 原始佣金
                        'commission_level' => 0,   // 分佣层级
                        'commission_rules' => '',   // 分佣层级
                        'agent_level' => 0 ,             // 分佣时分销商等级
                        'commission_time' => time()
                    ];
                    //创建佣金明细
                    $commissionReward = RewardModel::create($commissionRewardParams);
                    //动态
                    $user = User::get($agent['id']);
                    LogModel::add($agent['id'], 'reward', [
                        'type' => 'paid',
                        'reward' => $commissionReward,
                    ], $user);
                    WalletService::change($agent['id'], 'commission', $levelTmp1, 'buy_commion_good', [
                        'order_id' => $order['id'],
                    ]);

                    WalletService::change($agent['id'], 'money', $levelTmp1_2money, 'buy_commion_good1', [
                        'order_id' => $order['id'],
                    ]);

                }

            }
            \think\Log::info('找星星结束');

            $this->fenhong($order,$shopGood['bonus1'],$shopGood['bonus2'],$shopGood['bonus3'],$shopGood['bonus4'],$shopGood['bonus5'],$shopGood['bonus6'],$shopGood['bonus7']);
            $this->jiaquanfenhong($order,$shopGood['bonus_rate']);
            if($shopGood['static_release']==1){
                $this->user_integral_release($order);
            }


        }
    }

    /**
     * @Description: 获取上限第一个xx等级分销商
     * @param $level
     */
    public function getOneUpAgency($uid, $level)
    {
        $return = [];
        if($uid <= 0 || $level <= 0) return [];
        while (true)
        {
            $user = Db::name("user")->query("select a.id,a.parent_user_id,b.level from fa_user a left join fa_shopro_commission_agent b on a.id=b.user_id where a.id={$uid}");
            if(empty($user))
            {
                break;
            }
            $user = current($user);
            $puid = $user['parent_user_id'] ?? 0;
            if($puid <= 0)
            {
                break;
            }
            //$puser = Db::name("user")->query("select a.id,a.parent_user_id,b.level from fa_user a left join fa_shopro_commission_agent b on a.id=b.user_id where a.parent_user_id={$puid}");
            $puser = Db::name("user")->query("select a.id,a.parent_user_id,b.level from fa_user a left join fa_shopro_commission_agent b on a.id=b.user_id where a.id={$puid}");
            if(empty($puser))
            {
                break;
            }
            $puser = current($puser);
            if($puser['level'] >=$level)
            {
                $return = $puser;
                break;
            }
            $uid = $puser['id'];
        }
        return $return;
    }


    // 真实反向 加库存减销量（订单退全款）
    public function backStockSale($order, $items = [])
    {
        if (!$items) {
            $items = OrderItem::where('order_id', $order['id'])->select();
        }
        foreach ($items as $key => $item) {
            // 返还商品销量
            Goods::where('id', $item->goods_id)->setDec('sales', $item->goods_num);

            // 返还规格库存
            $skuPrice = SkuPrice::where('id', $item->goods_sku_price_id)->find();
            if ($skuPrice) {
                SkuPrice::where('id', $item->goods_sku_price_id)->setInc('stock', $item->goods_num);         // 返还库存
                SkuPrice::where('id', $item->goods_sku_price_id)->setDec('sales', $item->goods_num);         // 减少销量
                // 库存预警检测
                $this->checkStockWarning($skuPrice);
            }

            if ($item->item_goods_sku_price_id) {
                if ($order['type'] == 'score') {
                    // 积分商城商品，扣除积分规格库存
                    ScoreSkuPrice::where('id', $item->item_goods_sku_price_id)->setInc('stock', $item->goods_num);     // 返还库存
                    ScoreSkuPrice::where('id', $item->item_goods_sku_price_id)->setDec('sales', $item->goods_num);       // 减少销量

                } else {
                    // 扣除活动库存
                    ActivitySkuPriceModel::where('id', $item->item_goods_sku_price_id)->setInc('stock', $item->goods_num);     // 返还库存
                    ActivitySkuPriceModel::where('id', $item->item_goods_sku_price_id)->setDec('sales', $item->goods_num);      // 减少销量
                }
            }
        }
    }



    // cache 正向加销量，添加订单之前拦截
    public function cacheForwardSale($buyInfo) {
        $goods = $buyInfo['goods'];
        $activity = $goods['activity'];

        if (has_redis()) {
            $keys = ActivityRedisFacade::keysActivity([
                'goods_id' => $goods->id,
                'goods_sku_price_id' => $buyInfo['current_sku_price']->id,
            ], [
                'activity_id' => $activity['id'],
                'activity_type' => $activity['type'],
            ]);

            extract($keys);

            // 活动商品规格
            $goodsSkuPrice = Redis::HGET($keyActivity, $keyGoodsSkuPrice);
            $goodsSkuPrice = json_decode($goodsSkuPrice, true);
            // 活动商品库存
            $stock = $goodsSkuPrice['stock'] ?? 0;

            // 当前销量 + 购买数量 ，salekey 如果不存在，自动创建
            $sale = Redis::HINCRBY($keyActivity, $keySale, $buyInfo['goods_num']);

            if ($sale > $stock) {
                $sale = Redis::HINCRBY($keyActivity, $keySale, -$buyInfo['goods_num']);
                error_stop('活动商品库存不足');
            }
        }
    }


    // cache 反向减销量，取消订单/订单自动关闭 时候
    public function cacheBackSale($order) {
        $items = OrderItem::where('order_id', $order['id'])->select();

        foreach ($items as $key => $item) {
            $this->cacheBackSaleByItem($item);
        }
    }



    // 通过 OrderItem 减预库存
    private function cacheBackSaleByItem($item)
    {
        if (has_redis()) {
            $keys = ActivityRedisFacade::keysActivity([
                'goods_id' => $item['goods_id'],
                'goods_sku_price_id' => $item['goods_sku_price_id'],
            ], [
                'activity_id' => $item['activity_id'],
                'activity_type' => $item['activity_type'],
            ]);

            extract($keys);

            if (Redis::EXISTS($keyActivity) && Redis::HEXISTS($keyActivity, $keySale)) {
                $sale = Redis::HINCRBY($keyActivity, $keySale, -$item['goods_num']);
            }
    
            return true;
        }
    }


    /**
     * 获取库存锁定 key
     *
     * @param int $goods_id
     * @param int $goods_sku_price_id
     * @return string
     */
    private function getLockedGoodsKey($goods_id, $goods_sku_price_id, $order_type = 'goods')
    {
        $prefix = 'locked_goods_num:' . $order_type . ':' . $goods_id . ':' . $goods_sku_price_id;
        return $prefix;
    }
}
